package com.github.easyms.server.config.shiro;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.github.easyms.common.constant.GlobalConstants;
import com.github.easyms.common.property.EasymsProperties;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.Locale;

/**
 * JWT工具
 *
 * @author Leo.Liao
 * @date 2020-04-10 13:33:13
 */
@Component
public class JwtService {

    @Resource
    private EasymsProperties easymsProperties;

    /**
     * 校验token是否正确
     *
     * @param token
     * @return
     */
    public boolean verify(String token) {
        String secret = getClaim(token, GlobalConstants.SecurityKey.USER) + easymsProperties.getJwtKey();
        Algorithm algorithm = Algorithm.HMAC256(secret);
        JWTVerifier verifier = JWT.require(algorithm).build();
        verifier.verify(token);
        return true;
    }

    /**
     * 判断是否是即将失效的Token（有效时长小于5分钟）
     * @param token
     * @return
     */
    public boolean isAboutToExpire(String token,Integer term){
        // token签发时间
        LocalDateTime issuedTime = LocalDateTime.ofInstant(getIssuedTime(token).toInstant(),ZoneId.systemDefault());
        LocalDateTime expireTime = issuedTime.plusMinutes(term);
        LocalDateTime now = LocalDateTime.now();
        Duration duration = Duration.between(now,expireTime);
        return duration.toMinutes() < 5;
    }

    /**
     * 获取过期时间
     * @param token
     * @return
     */
    public Date getExpireTime(String token){
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getExpiresAt();
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 获取签发时间
     * @param token
     * @return
     */
    public Date getIssuedTime(String token){
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getIssuedAt();
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 获得Token中的信息无需secret解密也能获得
     *
     * @param token
     * @param claim
     * @return
     */
    public String getClaim(String token, String claim) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim(claim).asString();
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 生成签名，无过期时间（本项目在redis中控制token过期时间）
     *
     * @param userId
     * @param roleId
     * @return
     */
    public String sign(String userId,String roleId) {
        // 帐号加JWT私钥加密
        String secret = userId + easymsProperties.getJwtKey();
        LocalDateTime tokenExpiresAt = LocalDateTime.now().plusYears(1);
        Algorithm algorithm = Algorithm.HMAC256(secret);
        return JWT.create()
                .withClaim(GlobalConstants.SecurityKey.USER, userId)
                .withClaim(GlobalConstants.SecurityKey.ROLE,roleId)
                .withIssuedAt(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()))
                .sign(algorithm);
    }

}
